package com.yk.system.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yk.api.system.dto.DeviceDTO;
import com.yk.api.system.dto.GroupDTO;
import com.yk.api.system.dto.VideoDTO;
import com.yk.common.core.constant.NumberConstant;
import com.yk.common.core.domain.BasePageQuery;
import com.yk.common.core.domain.PageResult;
import com.yk.common.core.domain.Result;
import com.yk.common.core.utils.LoginHelper;
import com.yk.common.log.annotation.Log;
import com.yk.common.log.constant.LogConstants;
import com.yk.common.log.enums.BusinessType;
import com.yk.system.convert.GroupConvert;
import com.yk.system.entity.Group;
import com.yk.system.entity.GroupConfiguration;
import com.yk.system.entity.GroupDevice;
import com.yk.system.service.GroupConfigurationService;
import com.yk.system.service.GroupDeviceService;
import com.yk.system.service.GroupService;
import com.yk.system.service.VideoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 场景管理 yk-system
 *
 * @author lmx
 * @date 2023/10/16 18:15
 */
@Api(tags = "场景管理")
@RestController
@RequiredArgsConstructor
@RequestMapping("/group")
public class GroupController {

    private final GroupService groupService;
    private final GroupConvert groupConvert;
    private final GroupDeviceService groupDeviceService;
    private final GroupConfigurationService groupConfigurationService;
    private final VideoService videoService;

    @Log(title = "场景", businessType = BusinessType.INSERT)
    @ApiOperation("新增")
    @PostMapping("/add")
    public Result<Void> add(@Validated @RequestBody GroupDTO dto) {
        Long userId = LoginHelper.getLoginUserId();
        long groupId = IdWorker.getId();
        dto.setId(groupId);
        groupService.save(groupConvert.dto2Entity(dto));
        if (CollUtil.isNotEmpty(dto.getDeviceDTOList())) {
            List<GroupDevice> addList = CollUtil.newArrayList();
            List<DeviceDTO> deviceDTOList = dto.getDeviceDTOList();
            for (int i = 0; i < deviceDTOList.size(); i++) {
                DeviceDTO deviceDTO = deviceDTOList.get(i);
                addList.add(new GroupDevice(groupId, deviceDTO.getId(), userId, i + 1));
            }
            groupDeviceService.batchInsert(addList);
        }
        return Result.ok2Log(LogConstants.ADD + dto.getName());
    }

    @Log(title = "场景", businessType = BusinessType.UPDATE)
    @ApiOperation("编辑")
    @PostMapping("/edit")
    public Result<Void> edit(@Validated @RequestBody GroupDTO dto) {
        Long userId = LoginHelper.getLoginUserId();
        groupService.updateById(groupConvert.dto2Entity(dto));
        // 删除关联
        LambdaQueryWrapper<GroupDevice> lambda = new LambdaQueryWrapper<>();
        lambda.eq(GroupDevice::getGroupId, dto.getId());
        groupDeviceService.remove(lambda);
        // 需要关联
        if (CollUtil.isNotEmpty(dto.getDeviceDTOList())) {
            List<GroupDevice> addList = CollUtil.newArrayList();
            List<DeviceDTO> deviceDTOList = dto.getDeviceDTOList();
            for (int i = 0; i < deviceDTOList.size(); i++) {
                DeviceDTO deviceDTO = deviceDTOList.get(i);
                addList.add(new GroupDevice(dto.getId(), deviceDTO.getId(), userId, i + 1));
            }
            groupDeviceService.batchInsert(addList);
        }
        return Result.ok2Log(LogConstants.UPDATE + dto.getName());
    }

    @ApiOperation("排序")
    @PostMapping("/sort")
    public Result<Void> sort(@Validated @RequestBody GroupDTO dto) {
        Long userId = LoginHelper.getLoginUserId();
        groupService.updateById(groupConvert.dto2Entity(dto));
        // 删除关联
        LambdaQueryWrapper<GroupDevice> lambda = new LambdaQueryWrapper<>();
        lambda.eq(GroupDevice::getGroupId, dto.getId());
        groupDeviceService.remove(lambda);
        // 需要关联
        if (CollUtil.isNotEmpty(dto.getDeviceDTOList())) {
            List<GroupDevice> addList = CollUtil.newArrayList();
            List<DeviceDTO> deviceDTOList = dto.getDeviceDTOList();
            for (int i = 0; i < deviceDTOList.size(); i++) {
                DeviceDTO deviceDTO = deviceDTOList.get(i);
                addList.add(new GroupDevice(dto.getId(), deviceDTO.getId(), userId, i + 1));
            }
            groupDeviceService.batchInsert(addList);
        }
        return Result.ok2Log(LogConstants.UPDATE + dto.getName());
    }

    @Log(title = "场景管理", businessType = BusinessType.DELETE)
    @ApiOperation("删除")
    @GetMapping("/delete/{id}")
    public Result<Void> delete(@PathVariable Long id) {
        Long userId = LoginHelper.getLoginUserId();
        Group group = groupService.getById(id);
        if (Objects.isNull(group)) {
            return Result.fail("该场景不存在");
        }
        GroupConfiguration groupConfiguration = groupConfigurationService.selectByGroupId(id);
        if (Objects.nonNull(groupConfiguration)) {
            return Result.fail("该场景下存在关联的组态信息");
        }
        List<DeviceDTO> dtoList = groupDeviceService.listByGroupId(id, userId);
        if (CollUtil.isNotEmpty(dtoList)) {
            return Result.fail("该场景下存在关联的设备");
        }
        List<VideoDTO> videoDTOS = videoService.listByGroupId(id);
        if (CollUtil.isNotEmpty(videoDTOS)) {
            return Result.fail("该场景下存在关联的摄像头");
        }
        groupService.removeById(id);
        return Result.ok2Log(LogConstants.DELETE + group.getName());
    }

    @ApiOperation("查看")
    @GetMapping("/view/{id}")
    public Result<GroupDTO> view(@PathVariable Long id) {
        Group tbGroup = groupService.getById(id);
        return Result.data(groupConvert.entity2Dto(tbGroup));
    }

    @ApiOperation("分页查询")
    @PostMapping("/page")
    public PageResult<GroupDTO> page(@RequestBody BasePageQuery<GroupDTO> pageParam) {
        Long userId = LoginHelper.getLoginUserId();
        LambdaQueryWrapper<Group> lambda = new QueryWrapper<Group>().lambda();
        buildCondition(lambda, pageParam.getParam());
        lambda.eq(Group::getCreatedBy, LoginHelper.getLoginUserId());
        IPage<GroupDTO> page = groupService.page(new Page<>(pageParam.getPageNum(), pageParam.getPageSize()), lambda).convert(groupConvert::entity2Dto);
        if (CollUtil.isNotEmpty(page.getRecords())) {
            page.getRecords().forEach(it -> it.setDeviceDTOList(groupDeviceService.listByGroupId(it.getId(), userId)));
        }
        return PageResult.success(page.getRecords(), page.getTotal());
    }

    @ApiOperation("小程序场景列表")
    @PostMapping("/appList")
    public Result<List<GroupDTO>> appPage(@RequestBody GroupDTO dto) {
        List<GroupDTO> collect = groupService.appList(dto);
        return Result.data(collect);
    }

    @ApiOperation("全量查询")
    @PostMapping("/list")
    public Result<List<GroupDTO>> list() {
        LambdaQueryWrapper<Group> lambda = new QueryWrapper<Group>().lambda();
        lambda.eq(Group::getCreatedBy, LoginHelper.getLoginUserId());
        List<Group> list = groupService.list(lambda);
        if (CollUtil.isEmpty(list)) {
            return Result.ok();
        }
        List<GroupDTO> dtoList = list.stream().map(it -> {
            GroupDTO groupDTO = groupConvert.entity2Dto(it);
            Integer count = groupConfigurationService.countByGroupId(groupDTO.getId());
            if (Objects.nonNull(count) && count > 0) {
                groupDTO.setExistsConfiguration(Boolean.TRUE);
            } else {
                groupDTO.setExistsConfiguration(Boolean.FALSE);
            }
            return groupDTO;
        }).collect(Collectors.toList());
        return Result.data(dtoList);
    }

    @ApiOperation("根据id查询当前数据所在页码")
    @PostMapping("/getPageNum")
    public Result<Integer> getPageNum(@RequestBody BasePageQuery<GroupDTO> pageParam) {
        GroupDTO param = pageParam.getParam();
        if (Objects.isNull(param) || Objects.isNull(param.getId())) {
            return Result.data(NumberConstant.ZERO);
        }
        Group group = groupService.getById(param.getId());
        if (Objects.isNull(group)) {
            return Result.data(NumberConstant.ZERO);
        }
        return Result.data(groupService.getPageNum(param.getId(), pageParam.getPageSize()));
    }

    /**
     * 构造查询条件
     */
    private void buildCondition(LambdaQueryWrapper<Group> lambda, GroupDTO param) {
        if (Objects.nonNull(param)) {
            lambda.like(StrUtil.isNotEmpty(param.getQ()), Group::getName, param.getQ());

            if (Objects.nonNull(param.getStartTime()) && Objects.nonNull(param.getEndTime())) {
                lambda.between(Group::getCreatedAt, param.getStartTime(), param.getEndTime());
            }
        }
        lambda.orderByDesc(Group::getCreatedAt);
    }
}
